using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using NSMBe4;

namespace MKDS_Course_Editor.UI
{
    public partial class GraphicsControl : UserControl
    {
        bool sm64fix = false;
        string grap;
        string palll;
        string mappp;
        public GraphicsControl(string g, string p, GraphicsType t, string m = null)
        {
            InitializeComponent();
            grap = g;
            palll = p;
            mappp = m;
            toolStrip1.Renderer = new Form2.MyRender();
            T = t;
            toolStripComboBox1.SelectedIndex = 0;
            toolStripComboBox2.SelectedIndex = 0;
            for (int i = 1; i < 129; i++)
            {
                //powers.Add(i * 8);
                toolStripComboBox3.Items.Add((i * 8).ToString());
            }
            bool gcomp;
            bool pltcomp;
            bool mapcomp;
            toolStripComboBox3.SelectedIndex = 0;
            switch (t)
            {
                case GraphicsType.Raw:
                    if (m != null)
                    {
                        if (m.EndsWith("isc.bin")) { sm64fix = true; }
                    }
                    path = File.ReadAllBytes(g);
                    path = tryDecompress(path, out gcomp);
                    byte[] plt = tryDecompress(File.ReadAllBytes(p), out pltcomp);
                    Color[] c = Tinke.Convertir.BGR555(plt);
                    pal = c;
                    map = (m == null ? null : tryDecompress(File.ReadAllBytes(m), out mapcomp));
                    break;

            }
        }
        private byte[] tryDecompress(byte[] file, out bool done)
        {
            try
            {
                byte[] decomp = ROM.LZ77_Decompress(file);
                if (decomp.Length == 0)
                {
                    done = false;
                    return file;
                }
                done = true;
                return decomp;
            }
            catch (Exception)
            {
                done = false;
                return file;
            }
        }
        List<int> powers = new List<int>();
        byte[] path;
        Color[] pal;
        byte[] map;
        private void GraphicsControl_Load(object sender, EventArgs e)
        {
            c = pal;
            int nr = 0;
            toolStripComboBox2.Items.Clear();
            for (int i = 0; i < c.Length; i++)
            {
                if (i / (toolStripComboBox1.SelectedIndex == 0 ? 16 : 256) == nr)
                {
                    toolStripComboBox2.Items.Add(nr.ToString());
                    nr++;
                }
            }
            toolStripComboBox2.SelectedIndex = 0;
            if (map != null)
            {
                toolStripComboBox2.Enabled = false;
                toolStripLabel3.Visible = true;
                toolStripTextBox1.Visible = true;
            }
            Render();
        }
        byte[] data2;
        Color[] c;
        void Render()
        {
            Bitmap b = new Bitmap(1, 1);
            switch (T)
            {
                case GraphicsType.Default:
                    {
                        break;
                    }
                case GraphicsType.NCGR:
                    {
                        break;
                    }
                case GraphicsType.Raw:
                    {
                        //if (data2 == null)
                        //{
                        //    data2 = ROM.LZ77_Decompress(path);
                        //}
                        data2 = path;
                        if (toolStripComboBox1.SelectedIndex == 0)
                        {
                            b = new Bitmap((int)(data2.Length / 32) * 8, 8);
                            int offset = 0;
                            for (int i = 0; i < data2.Length / 32; i++)
                            {
                                for (int TileY = 0; TileY < 8; TileY++)
                                {
                                    for (int TileX = 0; TileX < 4; TileX++)
                                    {
                                        byte by = data2[offset];
                                        b.SetPixel((i * 8 + TileX * 2) + 1, TileY, gpalette(by / 16 + (int)toolStripComboBox2.SelectedIndex * 16, c));
                                        b.SetPixel(i * 8 + TileX * 2, TileY, gpalette(by % 16 + (int)toolStripComboBox2.SelectedIndex * 16, c));
                                        offset++;
                                    }
                                }
                            }
                        }
                        else
                        {
                            b = new Bitmap((int)(data2.Length / 64) * 8, (map != null ? 16 : 8));
                            int offset = 0;
                            for (int i = 0; i < data2.Length / 64; i++)
                            {
                                int num4 = i * 8;
                                for (int TileY = 0; TileY < 8; TileY++)
                                {
                                    for (int TileX = 0; TileX < 8; TileX++)
                                    {
                                        byte by = data2[offset];
                                        //b.SetPixel(i * 8 + TileX, TileY, gpalette(by + (int)toolStripComboBox2.SelectedIndex * 256, c));
                                        b.SetPixel(num4 + TileX, TileY, gpalette(by + (int)toolStripComboBox2.SelectedIndex * 256, c));
                                        //if (c.Length > 0x200)
                                        //{
                                        if (map != null)
                                        {
                                            b.SetPixel(num4 + TileX, TileY + 8, gpalette(by + 256, c));
                                        }
                                        //}
                                        offset++;
                                    }
                                }
                            }

                        }
                        break;
                    }
            }
            if (map != null)
            {
                byte[] eLayoutFile = map;
                int LayoutCount = eLayoutFile.Length / 2;
                LayoutCount -= 2;
                if (sm64fix)
                {
                    LayoutCount -= LayoutCount / 8;
                }
                int width = LayoutCount * 8;
                //int height = eLayoutFile[2] << 4;
                Bitmap BG = new Bitmap(width, 8, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                Graphics BGGraphics = Graphics.FromImage(BG);
                BGGraphics.Clear(Color.Transparent);

                int FilePos = 4 + (sm64fix ? 1 : 0);
                int TileNum;
                byte ControlByte;
                Rectangle SrcRect;
                int SrcX = 0;
                int SrcY = 0;
                int TileOffset = int.Parse(toolStripTextBox1.Text);
                Bitmap fliptile = new Bitmap(8, 8);
                Graphics g = Graphics.FromImage(fliptile);
                int ind = 0;
                int last = 0;
                Console.WriteLine("==Start==");
                for (int TileIdx = 0; TileIdx < LayoutCount; TileIdx++)
                {
                    TileNum = eLayoutFile[FilePos];
                    ControlByte = eLayoutFile[FilePos + 1];
                    TileNum |= (ControlByte & 3) << 8;
                    TileNum -= TileOffset;
                    Console.WriteLine(TileNum);
                    SrcRect = new Rectangle(TileNum * 8, (ControlByte & 16) != 0 ? 8 : 0, 8, 8);
                    if ((ControlByte & 4) != 0 || (ControlByte & 8) != 0)
                    {
                        g.DrawImage(b, 0, 0, SrcRect, GraphicsUnit.Pixel);
                        if ((ControlByte & 4) != 0)
                            fliptile.RotateFlip(RotateFlipType.RotateNoneFlipX);
                        if ((ControlByte & 8) != 0)
                            fliptile.RotateFlip(RotateFlipType.RotateNoneFlipY);
                        BGGraphics.DrawImage(fliptile, SrcX, SrcY);
                    }
                    else
                    {
                        BGGraphics.DrawImage(b, SrcX, SrcY, SrcRect, GraphicsUnit.Pixel);
                    }
                    SrcX += 8;
                    if (SrcX >= width) { SrcX = 0; SrcY += 8; }
                    FilePos += 2;
                    if (sm64fix && ind == 3)
                    {
                        ind = 0 - last;
                        if (last != 1)
                        {
                            FilePos++;
                            last = eLayoutFile[FilePos - 1];
                        }
                        else
                        {
                            last = 0;
                        }
                    }
                    else if (sm64fix)
                    {
                        ind++;
                    }
                }
                pictureBox1.Image = CutImage(BG, Convert.ToInt32(toolStripComboBox3.SelectedItem), 1);
            }
            else
            {
                //if (toolStripComboBox1.SelectedIndex == 0)
                //{
                pictureBox1.Image = CutImage(b, Convert.ToInt32(toolStripComboBox3.SelectedItem), 1);
                //}
                //else
                //{
                //    pictureBox1.Image = CutImage(b, Convert.ToInt32(toolStripComboBox3.SelectedItem), 2);
                //}
            }
        }

        public enum GraphicsType
        {
            Default,
            NCGR,
            Raw
        };
        public static Bitmap CutImage(Image im, int width, int blockrows)
        {
            int blocksize = im.Height / blockrows;
            int blockcount = im.Width / blocksize;

            int cols = width / blocksize;
            int rows = blockcount / cols;

            Bitmap b = new Bitmap(cols * blocksize, rows * blocksize * blockrows);
            Graphics g = Graphics.FromImage(b);
            g.Clear(Color.Gray);

            Rectangle SourceRect = new Rectangle(0, 0, cols * blocksize, blocksize);
            Rectangle DestRect = new Rectangle(0, 0, cols * blocksize, blocksize);


            for (int r = 0; r < blockrows; r++)
            {
                SourceRect.Y = r * blocksize;
                for (int i = 0; i < rows; i++)
                {
                    SourceRect.X = i * cols * blocksize;
                    DestRect.Y = i * blocksize + r * rows * blocksize;

                    g.DrawImage(im, DestRect, SourceRect, GraphicsUnit.Pixel);
                }
            }

            return b;
        }
        GraphicsType T;
        private Color gpalette(int n, Color[] palette)
        {
            if (n >= palette.Length || n <= -1)
                return Color.Pink;
            return palette[n];
        }

        private void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (path != null && c != null)
            {
                toolStripComboBox2.Items.Clear();
                int nr = 0;
                for (int i = 0; i < c.Length; i++)
                {
                    if (i / (toolStripComboBox1.SelectedIndex == 0 ? 16 : 256) == nr)
                    {
                        toolStripComboBox2.Items.Add(nr.ToString());
                        nr++;
                    }
                }
                toolStripComboBox2.SelectedIndex = 0;
                Render();
            }
        }

        private void toolStripComboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (path != null && c != null)
            {
                Render();
            }
        }

        private void toolStripComboBox3_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (path != null && c != null)
            {
                Render();
            }
        }

        private void toolStripTextBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void toolStripTextBox1_Leave(object sender, EventArgs e)
        {
            int o;
            if (!int.TryParse(toolStripTextBox1.Text, out o))
            {
                Render();
            }
        }

        private void toolStripTextBox1_Validating(object sender, CancelEventArgs e)
        {
            int o;
            e.Cancel = !int.TryParse(toolStripTextBox1.Text, out o);
            if (!e.Cancel)
            {
                Render();
            }
        }

        private void toolStripTextBox1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                int o;
                if (!int.TryParse(toolStripTextBox1.Text, out o))
                {
                    Render();
                }
            }
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK
                && openFileDialog1.FileName.Length > 0)
            {
                Bitmap b = new Bitmap(openFileDialog1.FileName);
                if (toolStripComboBox1.SelectedIndex == 0) //4bpp
                {
                    if (map != null)
                    {
                        ImageTiler t = new ImageTiler(b, 0);
                        MemoryStream m = new MemoryStream();
                        EndianBinaryWriter er = new EndianBinaryWriter(m, Endianness.LittleEndian);
                        //for (int i = 0; i < b.Width*b.Height; i++)
                        //{
                        er.Write((byte)0x10);
                        er.Write((byte)0x00);
                        er.Write((byte)0x20);
                        er.Write((byte)0x00);
                        for (int yt = 0; yt < b.Height / 8; yt++)
                            for (int xt = 0; xt < b.Width / 8; xt++)
                            {
                                int npalette = (0 & 0xf) << 12;
                                int yFlip = (0 & 0x1) << 11;
                                int xFlip = (0 & 0x1) << 10;
                                int data = npalette + yFlip + xFlip + (t.tileMap[xt, yt] & 0x3FF);
                                er.Write((ushort)data);
                            }
                        map = m.ToArray();
                        er.Close();
                        //}
                        bool trans = (MessageBox.Show("Use transparent?", "Question?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes ? true : false);
                        Color[] cll = ImageIndexer.createPaletteForImage(t.tileBuffer, 16, trans);
                        c = cll;
                        byte[] palettedImage = new byte[t.tileBuffer.Width * t.tileBuffer.Height / 2];
                        int tileCount = t.tileBuffer.Width * t.tileBuffer.Height / 64;
                        int tileWidth = t.tileBuffer.Width / 8;
                        int nr = 0;
                        int nr2 = 0;
                        for (int ti = 0; ti < tileCount; ti++)
                            for (int y = 0; y < 8; y++)
                                for (int x = 0; x < 8; x++)
                                {
                                    int tx = (ti % tileWidth) * 8;
                                    int ty = (int)(ti / tileWidth) * 8;
                                    //palettedImage[ti * 64 + y * 8 + x] =
                                    //    imageData[tx + x, ty + y];
                                    int c2 = ImageIndexer.closest(t.tileBuffer.GetPixel(tx + x, ty + y), c.ToList().GetRange((0 * 16), 16).ToArray());
                                    palettedImage[nr] |= (nr2 == 0 ? (byte)((c2 & 0xf)) : (byte)((c2 & 0xf) << 4));
                                    if (nr2 == 0)
                                    {
                                        nr2++;
                                    }
                                    else
                                    {
                                        nr2 = 0;
                                        nr++;
                                    }
                                }
                        path = palettedImage;
                    }
                    else
                    {
                        bool trans = (MessageBox.Show("Use transparent?", "Question?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes ? true : false);
                        Color[] cll = ImageIndexer.createPaletteForImage(b, 16, trans);
                        c = cll;
                        byte[] palettedImage = new byte[b.Width * b.Height / 2];
                        int tileCount = b.Width * b.Height / 64;
                        int tileWidth = b.Width / 8;
                        int nr = 0;
                        int nr2 = 0;
                        for (int ti = 0; ti < tileCount; ti++)
                            for (int y = 0; y < 8; y++)
                                for (int x = 0; x < 8; x++)
                                {
                                    int tx = (ti % tileWidth) * 8;
                                    int ty = (int)(ti / tileWidth) * 8;
                                    //palettedImage[ti * 64 + y * 8 + x] =
                                    //    imageData[tx + x, ty + y];
                                    int c2 = ImageIndexer.closest(b.GetPixel(tx + x, ty + y), c.ToList().GetRange((0 * 16), 16).ToArray());
                                    palettedImage[nr] |= (nr2 == 0 ? (byte)((c2 & 0xf)) : (byte)((c2 & 0xf) << 4));
                                    if (nr2 == 0)
                                    {
                                        nr2++;
                                    }
                                    else
                                    {
                                        nr2 = 0;
                                        nr++;
                                    }
                                }
                        path = palettedImage;
                    }
                }
                else //8bpp
                {

                }
            }
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == DialogResult.OK
                && saveFileDialog1.FileName.Length > 0)
            {
                pictureBox1.Image.Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Png);
            }
        }
    }
}
